#include "bsp.h"

// I2C引脚定义
#define I2C_SCL_GPIO_PORT       GPIOB
#define I2C_SCL_GPIO_PIN        GPIO_PIN_4
#define I2C_SDA_GPIO_PORT       GPIOB
#define I2C_SDA_GPIO_PIN        GPIO_PIN_5
#define I2C_SCL_INIT_STATE      GPIO_MODE_OUT_OD_HIZ_FAST
#define I2C_SDA_INIT_STATE      GPIO_MODE_OUT_OD_HIZ_FAST

#define Bit_RESET   0
#define Bit_SET     1

#define I2C_ACK     1
#define I2C_NACK    0

// 延时和超时相关常量
#define I2C_BIT_DELAY_US        5   // 位操作延时，单位为us
#define I2C_SCL_HIGH_US         10  // SCL高电平延时，单位为us
#define SCL_TIMEOUT_US          1000 // 等待SCL高电平的超时，单位为us
#define I2C_ACK_TIMEOUT_US      100  // ACK超时，单位为us

#define I2C_PIN_SDA GPIO_PIN_5
#define I2C_PIN_SCL GPIO_PIN_4

// 延时函数
void DELAY_APL_Delayus(unsigned char us)
{
    TIM_Delay_us(us);
}

// 等待SCL高电平，处理时钟拉伸
uint8_t wait_for_scl_high(void)
{
    uint32_t timeout = SCL_TIMEOUT_US;
    while (I2C_HAL_PinRead(I2C_PIN_SCL) == Bit_RESET && timeout > 0)
    {
        DELAY_APL_Delayus(1);
        timeout--;
    }
    return (timeout > 0) ? 1 : 0; // 1: 成功，0: 超时
}

// 产生ACK应答
void I2C_HAL_MasterSendAck(void)
{
    I2C_HAL_PinWrite(I2C_PIN_SDA, Bit_RESET);
    DELAY_APL_Delayus(I2C_BIT_DELAY_US);
    I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_SET);
    if (!wait_for_scl_high())
    {
        // 处理错误，例如记录或设置错误标志
    }
    DELAY_APL_Delayus(I2C_SCL_HIGH_US);
    I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_RESET);
    DELAY_APL_Delayus(I2C_BIT_DELAY_US);
    I2C_HAL_PinWrite(I2C_PIN_SDA, Bit_SET);
}

// 不产生ACK应答（NACK）
void I2C_HAL_MasterSendNack(void)
{
    I2C_HAL_PinWrite(I2C_PIN_SDA, Bit_SET);
    DELAY_APL_Delayus(I2C_BIT_DELAY_US);
    I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_SET);
    if (!wait_for_scl_high())
    {
        // 处理错误
    }
    DELAY_APL_Delayus(I2C_SCL_HIGH_US);
    I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_RESET);
    DELAY_APL_Delayus(I2C_BIT_DELAY_US);
}

// 初始化I2C GPIO引脚
void I2C_HAL_Init(void)
{
    GPIO_Init(I2C_SCL_GPIO_PORT, I2C_SCL_GPIO_PIN, I2C_SCL_INIT_STATE);
    GPIO_Init(I2C_SDA_GPIO_PORT, I2C_SDA_GPIO_PIN, I2C_SDA_INIT_STATE);
}

// 写入I2C引脚
void I2C_HAL_PinWrite(uint8_t pin_id, uint8_t bit_status)
{
    GPIO_TypeDef* port;
    GPIO_Pin_TypeDef pin;
    
    if (pin_id == I2C_PIN_SCL)
    {
        port = I2C_SCL_GPIO_PORT;
        pin = I2C_SCL_GPIO_PIN;
    }
    else if (pin_id == I2C_PIN_SDA)
    {
        port = I2C_SDA_GPIO_PORT;
        pin = I2C_SDA_GPIO_PIN;
    }
    else
    {
        return;
    }
    
    if (bit_status != Bit_RESET)
    {
        GPIO_WriteHigh(port, pin);
    }
    else
    {
        GPIO_WriteLow(port, pin);
    }
}

// 读取I2C引脚
uint8_t I2C_HAL_PinRead(uint8_t pin_id)
{
    GPIO_TypeDef* port;
    GPIO_Pin_TypeDef pin;
    
    if (pin_id == I2C_PIN_SCL)
    {
        port = I2C_SCL_GPIO_PORT;
        pin = I2C_SCL_GPIO_PIN;
    }
    else if (pin_id == I2C_PIN_SDA)
    {
        port = I2C_SDA_GPIO_PORT;
        pin = I2C_SDA_GPIO_PIN;
    }
    else
    {
        return 0;
    }
    
    return !!GPIO_ReadInputPin(port, pin);
}

// 生成I2C起始条件
void I2C_HAL_GenerateStart(void)
{
    I2C_HAL_PinWrite(I2C_PIN_SDA, Bit_SET);
    I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_SET);
    if (!wait_for_scl_high())
    {
        // 处理错误，例如记录或设置错误标志
    }
    DELAY_APL_Delayus(I2C_BIT_DELAY_US);
    I2C_HAL_PinWrite(I2C_PIN_SDA, Bit_RESET);
    DELAY_APL_Delayus(I2C_BIT_DELAY_US);
    I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_RESET);
    DELAY_APL_Delayus(I2C_BIT_DELAY_US);
}

// 生成I2C停止条件
void I2C_HAL_GenerateStop(void)
{
    I2C_HAL_PinWrite(I2C_PIN_SDA, Bit_RESET);
    DELAY_APL_Delayus(I2C_BIT_DELAY_US);
    I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_SET);
    if (!wait_for_scl_high())
    {
        // 处理错误
    }
    DELAY_APL_Delayus(I2C_BIT_DELAY_US);
    I2C_HAL_PinWrite(I2C_PIN_SDA, Bit_SET);
    DELAY_APL_Delayus(I2C_BIT_DELAY_US);
}

// 发送字节到从设备并返回ACK/NACK
uint8_t I2C_HAL_SendByte(uint8_t data)
{
    uint8_t bit_mask;
    uint8_t return_val = I2C_NACK;
    
    // 发送每个位，从最高位开始
    for (bit_mask = 0x80; bit_mask != 0; bit_mask >>= 1)
    {
        if (data & bit_mask)
        {
            I2C_HAL_PinWrite(I2C_PIN_SDA, Bit_SET);
        }
        else
        {
            I2C_HAL_PinWrite(I2C_PIN_SDA, Bit_RESET);
        }
        DELAY_APL_Delayus(I2C_BIT_DELAY_US);
        
        // 脉冲SCL高电平
        I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_SET);
        if (!wait_for_scl_high())
        {
            // 处理错误
        }
        DELAY_APL_Delayus(I2C_SCL_HIGH_US);
        I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_RESET);
        DELAY_APL_Delayus(I2C_BIT_DELAY_US);
    }
    
    // 释放SDA以接收ACK
    I2C_HAL_PinWrite(I2C_PIN_SDA, Bit_SET);
    DELAY_APL_Delayus(I2C_BIT_DELAY_US);
    
    // 脉冲SCL高电平以读取ACK
    I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_SET);
    if (!wait_for_scl_high())
    {
        // 处理错误
    }
    
    // 等待ACK，带超时
    uint32_t timeout = I2C_ACK_TIMEOUT_US;
    while (timeout--)
    {
        if (I2C_HAL_PinRead(I2C_PIN_SDA) == Bit_RESET)
        {
            return_val = I2C_ACK;
            break;
        }
        DELAY_APL_Delayus(1);
    }
    
    I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_RESET);
    DELAY_APL_Delayus(I2C_BIT_DELAY_US);
    
    return return_val;
}

// 从从设备读取字节并发送ACK/NACK
void I2C_HAL_ReadByte(uint8_t* data, uint8_t ack_status)
{
    uint8_t bit_mask;
    uint8_t data_temp = 0;
    
    // 释放SDA以读取
    I2C_HAL_PinWrite(I2C_PIN_SDA, Bit_SET);
    
    // 读取每个位
    for (bit_mask = 0x80; bit_mask != 0; bit_mask >>= 1)
    {
        DELAY_APL_Delayus(I2C_BIT_DELAY_US);
        I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_SET);
        if (!wait_for_scl_high())
        {
            // 处理错误
        }
        DELAY_APL_Delayus(I2C_SCL_HIGH_US);
        if (I2C_HAL_PinRead(I2C_PIN_SDA) == Bit_SET)
        {
            data_temp |= bit_mask;
        }
        I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_RESET);
        DELAY_APL_Delayus(I2C_BIT_DELAY_US);
    }
    *data = data_temp;
    
    // 发送ACK或NACK
    if (ack_status == I2C_ACK)
    {
        I2C_HAL_PinWrite(I2C_PIN_SDA, Bit_RESET);
    }
    else
    {
        I2C_HAL_PinWrite(I2C_PIN_SDA, Bit_SET);
    }
    DELAY_APL_Delayus(I2C_BIT_DELAY_US);
    I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_SET);
    if (!wait_for_scl_high())
    {
        // 处理错误
    }
    DELAY_APL_Delayus(I2C_SCL_HIGH_US);
    I2C_HAL_PinWrite(I2C_PIN_SCL, Bit_RESET);
    DELAY_APL_Delayus(I2C_BIT_DELAY_US);
}

